import GlobalData from "../GlobalData";
import { AlertManager, AlertType } from "../alert/AlertManager";
import { Const } from "../config/Const";

const NetLogger = console;
const wx = window["wx"];

/**
 * Http连接
 */
export default class BaseNet {
  /**
   * Post 请求
   *
   * @author
   * @static
   * @param {*} url
   * @param {*} [header]
   * @param {*} [body]
   * @returns
   * @memberof BaseNet
   */
  public static httpPost(url, body?, authon?) {
    return this._http("POST", url, body, authon);
  }

  /**
   * Get 请求
   * @param url 请求地址
   * @param header header
   * @param body body
   */
  public static httpGet(url, body?, authon?) {
    return this._http("GET", url, body, authon);
  }

  public static httpDelete(url, body?, authon?) {
    return this._http("DELETE", url, body, authon);
  }

  public static httpPut(url, body?, authon?) {
    return this._http("PUT", url, body, authon);
  }

  /**
   * 微信环境会使用 wx.request
   * 非微信环境使用 XMLHttpRequest
   *
   * @private
   * @static
   * @memberof BaseNet
   */
  private static __http: (method, url, body?, authon?) => Promise<any> = null;
  public static get directHttp(): (
    method,
    url,
    body?,
    authon?
  ) => Promise<any> {
    if (!this.__http) {
      this.__http = (() => {
        if (this._isWechat()) {
          return this._webHttp;
        } else {
          return this._webHttp;
        }
      })();
    }
    return this.__http;
  }

  private static _isWechat(): boolean {
    return !(typeof wx == "undefined");
  }

  private static _http(method, url, body?, authon?): Promise<any> {
    return new Promise((resolve, reject) => {
      this.directHttp(method, url, body, authon)
        .then((res) => {
          // NetLogger.info(res)
          if (
            (res.err && res.err != 0) ||
            (res.code && res.code != 0) 
            // (res?.data?.code && res?.data?.code != 0)
          ) {
            if (res?.data?.msg) {
              let msg = res?.data?.msg;
              if (res?.data?.info?.[0]?.ban_tip) {
                msg += res?.data?.info?.[0]?.ban_tip;
              }
              console.log("http ret: ", res);
              NetLogger.warn(
                `request ${method} ${url} ${body} res error res.err = ${res.err}, res.msg = ${msg}`
              );
              AlertManager.showNormalTips(msg);
              // AlertManager.showAlert(AlertType.COMMON, {
              //     desc: msg,
              //     errorcb: () => {
              //         jsb.reflection.callStaticMethod("com/jingyingxiaobing/blueclient/AppActivity", "exitApp", "()V");
              //     }
              // })
            }
            reject(res);
          } else if (res.ret && res.ret != 200) {
            AlertManager.showNormalTips(res.msg);
          } else {
            if (res.data) {
              resolve(res.data);
            } else if (res.info) {
              resolve(res);
            }else if (res) {
              resolve(res);
            }
          }
        })
        .catch((err) => {
          NetLogger.warn(`request ${method} ${url} ${body} error ${err}`);
          reject(err);
        });
    });
  }

  /**
   * 微信环境下的请求
   *
   * @author
   * @private
   * @static
   * @param {*} method
   * @param {*} url
   * @param {*} [body]
   * @returns {Promise<any>}
   * @memberof BaseNet
   */
  private static _wxHttp(method, url, body?, authon?): Promise<any> {
    return new Promise((resolve, reject) => {
      wx.request({
        url: url,
        data: body,
        method: method,
        header: {
          "content-type": "application/json",
          version: "1.0.0",
          Authorization: authon,
        },
        success: (res) => {
          // 微信的回调外面还封了一层data
          // NetLogger.debug(res);
          var a = res.data.code;
          let b = res.data.err;
          0 == a || 0 == b ? resolve(res.data) : reject(res.data);
        },
        fail: (err) => {
          reject({ code: -1, msg: "request请求失败", data: err });
        },
      });
    });
  }

  /**
   *浏览器环境下的请求
   *
   * @author
   * @private
   * @static
   * @param {*} method
   * @param {*} url
   * @param {Object} [body]
   * @returns {Promise<any>}
   * @memberof BaseNet
   */
  private static _webHttp(
    method,
    url,
    body?: Object,
    authon?: string,
    rspType: XMLHttpRequestResponseType = "json"
  ): Promise<any> {
    return new Promise((resolve, reject) => {
      let xmlHttp = new XMLHttpRequest();
      xmlHttp.timeout = 7000;

      const randomString = this.generateRandomString();
      const expire = Math.floor(Date.now()).toString(); // 当前时间戳，单位为秒

      const args = body || {};

      args["expire"] = expire;
      body["expire"] = expire;
      const signature = this.makeSignature(args);

      body["sign"] = signature;
      if (method == "GET" && body) {
        let str = "?";
        for (let k in body) {
          if (str != "?") {
            str += "&";
          }
          str += k + "=" + body[k];
        }
        url = url + str;
      }
      url = encodeURI(url);
      xmlHttp.open(method, url);
      xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4) {
          if (xmlHttp.status == 200) {
            if (rspType == "json") {
              resolve(JSON.parse(xmlHttp.responseText));
            } else {
              resolve(xmlHttp.response);
            }
          } else {
            reject({
              code: -1,
              msg: Error(`xmlHttp status = ${xmlHttp.status}`),
              data: {},
            });
          }
        } else {
          // NetLogger.debug(`xmlhttp readystate ${xmlHttp.readyState}`)
        }
      };
      xmlHttp.onerror = function () {
        reject({ code: -1, msg: Error("xmlhttp something error"), data: {} });
      };

      if (cc.sys.localStorage.getItem(Const.LOGIN_TOKEN)) {
        GlobalData.inst.token = cc.sys.localStorage.getItem(Const.LOGIN_TOKEN);
      }

      // xmlHttp.setRequestHeader("expire", expire);
      // xmlHttp.setRequestHeader("sign", signature);
      // // console.log("请求参数", expire,signature,GlobalData.inst.token)
      // console.log("expire", expire);
      // console.log("sign", signature);

      authon = GlobalData.inst.token || "";
      // set request header
      switch (rspType) {
        case "json":
          xmlHttp.setRequestHeader("content-type", "application/json");
          xmlHttp.setRequestHeader("version", "1.0.0");
          xmlHttp.setRequestHeader("Authorization", authon);
          break;
      }
      // set reponse type ，如果是二进制，则最好是arraybuffer或者blob
      if (rspType == "blob" || rspType == "arraybuffer") {
        xmlHttp.responseType = rspType;
      }
      console.log("请求参数", body);
      xmlHttp.send(body ? JSON.stringify(body) : "");
    });
  }

  private static generateRandomString() {
    let result = "";
    let characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    let charactersLength = characters.length;

    for (var i = 0; i < 16; i++) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }

    return result;
  }

  private static makeSignature(args: any, separator: string = "&^+"): string {
    const sortedArgs = Object.keys(args).sort();
    let stringA = "";
    console.log("makeSignature sortedArgs", sortedArgs);
    for (const k of sortedArgs) {
      //   stringA += `${args[k]}`;
      stringA += `${k}${separator}${args[k]}`;
    }

    const stringSignTemp = stringA;
    // console.log("makeSignature stringSignTemp", stringSignTemp);
    //@ts-ignore
    // console.log("abab",CryptoJS.MD5(stringSignTemp).toString().toUpperCase())
    //@ts-ignore
    return CryptoJS.MD5(stringSignTemp).toString();
  }
}
